#!/bin/sh

read_point_name="kedr-read-point"
write_point_name="kedr-write-point"
read_indicator_name="indicator_for_read"
write_indicator_name="indicator_for_write"

module_a_name="fsim_test_module_a"
module_a="module_a/${module_a_name}.ko"
module_b_name="fsim_test_module_b"
module_b="module_b/${module_b_name}.ko"
current_value_file="/sys/module/${module_a_name}/parameters/current_value"

device=kedr_test_device
debugfs_mount_point="@KEDR_TEST_DIR@/debugfs"
control_root="$debugfs_mount_point/kedr_fault_simulation"

# set_indicator point_name indicator_name
set_indicator()
{
    printf "$2" > "$control_root/points/$1/current_indicator"
}
# clear_indicator point_name
clear_indicator()
{
    printf "%s" "" > "$control_root/points/$1/current_indicator"
}
# get_indicator point_name
# print indicator to output
get_indicator()
{
    cat "$control_root/points/$1/current_indicator"
}


# simulate_point (read_point_name) | (write_point_name size)
simulate_point()
{
if test "$1" == "$read_point_name"; then
    dd "if=/dev/$device" of=/dev/null bs=1 count=1
elif test "$1" == "$write_point_name"; then
    dd "of=/dev/$device" if=/dev/zero bs=$2 count=1
fi
local result=$?
current_value=`cat "$current_value_file"`
return $result
}

commands_file="commands"
#Commands for load and unload module 'a;
commands_file_module_a="commands_a"
do_commands_script="sh @TEST_SCRIPTS_DIR@/do_commands.sh"

cat > "$commands_file" << eof

on_load @KEDR_FAULT_SIMULATION_LOAD_COMMAND@ || ! printf "Cannot load fault simulation module into kernel.\n"
on_unload @RMMOD@ "@KEDR_FAULT_SIMULATION_NAME@" || ! printf "Cannot unload fault simulation module.\n"
on_load mkdir -p "$debugfs_mount_point" || ! printf "Cannot create mount point for debugfs.\n"
on_load mount -t debugfs debugfs "$debugfs_mount_point" || ! printf "Cannot mount debugfs.\n"
on_unload umount "$debugfs_mount_point" || ! printf "Error occured while umounting debugfs.\n"
eof

cat > "$commands_file_module_a" << eof

on_load @INSMOD@ "$module_a" || ! printf "Cannot load module 'a' into the kernel.\n"
on_unload @RMMOD@ "$module_a_name" || ! printf "Fail to unload module 'a'.\n"

eof

if ! $do_commands_script "$commands_file" load; then
    printf "Cannot initialize test.\n"
    exit 1
fi

if ! $do_commands_script "$commands_file_module_a" load; then
    printf "Cannot load module 'a' correctly.\n"
    exit 1
fi


if ! @INSMOD@ "$module_b"; then
    printf "Cannot load module 'b' into the kernel.\n"
    $do_commands_script "$commands_file_module_a" unload && $do_commands_script "$commands_file" unload
    exit 1
fi

# Try to set write indicator for read point

if set_indicator "$read_point_name" "$write_indicator_name"; then
    printf "Indicator was set for a point which data it cannot process.\n"
    @RMMOD@ "$module_b_name"
    $do_commands_script "$commands_file_module_a" unload    
    $do_commands_script "$commands_file" unload
    
    exit 1
fi

if ! set_indicator "$read_point_name" "$read_indicator_name"; then
    printf "Cannot set indicator for the point.\n"
    @RMMOD@ "$module_b_name"
    
    $do_commands_script "$commands_file" unload
    
    exit 1
fi

# Try to unload module with point while we hold control file of this point opened
{
    # Module 'a' should correctly be unloaded even with file opened
    if ! $do_commands_script "$commands_file_module_a" unload; then
        printf "Cannot remove module 'a' with indicator control file opened.\n"
        @RMMOD@ "$module_b_name"
        $do_commands_script "$commands_file" unload
        exit 1
    fi

    # Operations with file may fail, but shouldn't crash kernel.
    cat <&9 > /dev/null
    echo "$write_indicator_name"  >&8 

    if ! $do_commands_script "$commands_file_module_a" load; then
        printf "Failed to load module 'a' again.\n"
        @RMMOD@ "$module_b_name"
        $do_commands_script "$commands_file" unload
        exit 1
    fi

} 9<"$control_root/points/${read_point_name}/current_indicator" 8>"$control_root/points/${read_point_name}/current_indicator"

@RMMOD@ "$module_b_name" && \
    $do_commands_script "$commands_file_module_a" unload && \
    $do_commands_script "$commands_file" unload
